﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IntegratedMeasuring.Storage;
using IntegratedMeasuring.ViewModels.Entity;
using IntegratedMeasuring.ViewModels.Scheme;
using Newtonsoft.Json;

namespace IntegratedMeasuring.Utils;

public class MesHandler
{
    private static readonly HttpClient client = new HttpClient();

    public static bool VerifyAvailable(out ApiResult apiResult)
    {
        if (string.IsNullOrEmpty(GV.ServerAddress))
        {
            apiResult = new ApiResult 
            { 
                code = 1,
                success = false,
                message = "Mes服务地址未填,数据将不会同步",
                data = null
            };
            return false;

        } else if (string.IsNullOrEmpty(GV.Token))
        {
            apiResult = new ApiResult 
            { 
                code = 2,
                success = false,
                message = "Mes服务令牌未填,数据将不会同步",
                data = null
            };
            return false;
        } else
        {
            apiResult = new ApiResult 
            { 
                code = 0,
                success = true,
                message = "",
                data = null
            };
            return true;
        }
    }

    /// <summary>
    /// 记录同步失败日志
    /// </summary>
    private static async Task<ApiResult> LogSyncFailureAsync(string data, string failReason, string syncUrl)
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) return apiResult;
        try
        {
            var logData = new SyncLogData
            {
                data = data,
                failReason = failReason,
                addTime = DateTime.Now,
                syncUrl = syncUrl
            };

            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 序列化数据
            var jsonContent = JsonConvert.SerializeObject(logData);
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            // 发送请求
            var response = await client.PostAsync($"{GV.ServerAddress}/SyncLog/SyncLogAdd", content);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            return JsonConvert.DeserializeObject<ApiResult>(responseString);
        }
        catch (Exception ex)
        {
            return new ApiResult 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }

    public static async Task<bool> UploadOrderToMes()
    {
        bool actionFlag = true;
        
        // 获取本地未同步的工单数据
        List<ProductionOrder> orders = await BaseDataStorage.Instance.QueryOrderAboutNotSynch();
        for (int i = 0; i < orders.Count; i++)
        {
            // 如果第一个都没传上去，则认为网络不通畅，则停止后续任务
            ApiResult apiResult = await SendOrderDataAsync(new MesOrdersSchema()
            {
                order = orders[i].Name,
                param = orders[i].TestConditions,
                instrument = GV.InstrumentModel.ToString(),
                orderNum = orders[i].PlanNumber,
                finishedNum =orders[i].FailNumber + orders[i].PassNumber,
                defects = orders[i].FailNumber,
                accepts = orders[i].PassNumber,
                createdBy = "IntegratedMeasuring",
                createdTime = orders[i].CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                updatedBy = "IntegratedMeasuring",
                updatedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                inUse = true,
                lotNum = orders[i].BatchNumber,
                isAnc = true,
                workStation = GV.DeviceNumber,
            });
            if (apiResult.code != 0)
            {
                actionFlag = false;
                break;
            }
            orders[i].IsSynch = true;
            await BaseDataStorage.Instance.UpdateProductionOrderAsync(orders[i]);
        }
        return actionFlag;
    }

    /// <summary>
    /// 上传工单数据到MES系统
    /// </summary>
    /// <param name="orderData">工单数据</param>
    /// <returns>API响应结果</returns>
    public static async Task<ApiResult> SendOrderDataAsync(MesOrdersSchema orderData)
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) 
            return apiResult;
        try
        {
            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 序列化数据
            var jsonContent = JsonConvert.SerializeObject(orderData);
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            // 发送请求
            var response = await client.PostAsync($"{GV.ServerAddress}/Orders/OrderInsert", content);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            var result = JsonConvert.DeserializeObject<ApiResult>(responseString);

            // 如果同步失败，记录日志
            if (!result.success)
            {
                await LogSyncFailureAsync(
                    JsonConvert.SerializeObject(orderData),
                    result.message,
                    "Orders/OrderInsert"
                );
            }

            return result;
        }
        catch (Exception ex)
        {
            // 发生异常时也记录日志
            await LogSyncFailureAsync(
                JsonConvert.SerializeObject(orderData),
                ex.Message,
                "Orders/OrderInsert"
            );

            return new ApiResult 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }

    /// <summary>
    /// 同步测试订单测试明细数据到MES系统
    /// </summary>
    /// <param name="testDetails">测试明细数据列表</param>
    /// <returns>API响应结果</returns>
    public static async Task<ApiResult> SyncTestDetailsAsync(ProductInfo testResult, ProductionOrder order, TestConditions? testConditions)
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) return apiResult;
        
        List<TestDetailData> testDetails = new List<TestDetailData>();

        List<TransItemData>? beautifyData = null;
        if (testConditions != null && testConditions.BeautifyData != null)
        {
            beautifyData = testConditions.BeautifyData;
        } 

        TestData _Data = new TestData();
        
        _Data.Result = testResult.Result == 1;
        _Data.Datas = new List<TestDataItem>();
        foreach (var item in testResult.TestDataDetail)
        {

            TransItemData? transItemData = null;
            if (beautifyData != null)
            {
                transItemData = beautifyData.FirstOrDefault(x => x.MinorTerm.Equals(item.MinorTerm) && x.Pri == item.Pri && x.Sec == item.Sec);
            }
            TestDataItem dataItem = new TestDataItem()
            {
                PRI = item.Pri,
                SEC = item.Sec,
                Pin = transItemData?.Pins ?? "",
                ShortPin = transItemData?.ShortCircuitPin ?? "",
                ItemType = item.MinorTerm,
                Freq = transItemData?.Freq ?? "",
                Vol = transItemData?.Vol ?? "",
                Nominal = transItemData?.Nominal ?? "",
                Min = transItemData?.LowerLimit ?? "",
                Max = transItemData?.UpperLimit ?? "",
                Result = item.Result == 1,
                ResultValue = item.DisplayDetectionValue + item.DisplayUnit,
                Test_Time = null
            };
            _Data.Datas.Add(dataItem);
        }
        
        TestDetailData testDetail = new TestDetailData()
        {
            Barcode = testResult.BarCode,
            Batch = testResult.BatchNumber,
            ChannelCount = GV.GetInstInfo().ChannelCount.ToString(),
            DataId = testResult.Id.ToString(),
            Duration = (testResult.EndTime - testResult.StartTime).ToString("mm:ss"),
            EndTime = testResult.EndTime.ToString("yyyy-MM-dd HH:mm:ss"),
            Field1 = "",
            Field2 = "",
            Field3 = "",
            Field4 = "",
            Field5 = "",
            Field6 = "",
            Field7 = "",
            Field8 = "",
            Field9 = "",
            FixtureType = "1",
            Line = GV.ProductionLineNumber,
            Operator = "IntegratedMeasuring",
            Order = testResult.OrderName,
            OutputCount = null,
            Param = testResult.TestCondition,
            ProductIndex = (int)GV.InstrumentModel,
            Result = testResult.Result == 1 ? "PASS" : "FAIL",
            Sn = null,
            StartTime = testResult.StartTime.ToString("yyyy-MM-dd HH:mm:ss"),
            Station = GV.DeviceNumber,
            Ver = 0,
            FinishedNum = order.PassNumber + order.FailNumber,
            Defects = order.FailNumber,
            Accepts = order.PassNumber,
            _Data = _Data,
        };
        
        testDetails.Add(testDetail);
        
        try
        {
            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 序列化数据
            var jsonContent = JsonConvert.SerializeObject(testDetails);
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            // 发送请求
            var response = await client.PostAsync($"{GV.ServerAddress}/Data/DataInsert", content);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            var result = JsonConvert.DeserializeObject<ApiResult>(responseString);

            // 如果同步失败，记录日志
            if (!result.success)
            {
                await LogSyncFailureAsync(
                    JsonConvert.SerializeObject(testDetails),
                    result.message,
                    "Data/DataInsert"
                );
            }
            else
            {
                BaseDataStorage.Instance.SetAsyncSuccessFlagById(testResult.Id);
            }

            return result;
        }
        catch (Exception ex)
        {
            // 发生异常时也记录日志
            await LogSyncFailureAsync(
                JsonConvert.SerializeObject(testDetails),
                ex.Message,
                "Data/DataInsert"
            );

            return new ApiResult 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }
    
    /// <summary>
    /// 同步测试订单明细历史数据到MES系统
    /// </summary>
    /// <param name="testDetails">测试明细数据列表</param>
    /// <returns>API响应结果</returns>
    public static async Task<ApiResult> SyncTestHistoryDetailsAsync()
    {
        List<TestDetailData> testDetails = new List<TestDetailData>();
        
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) return apiResult;
        try
        {
            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 序列化数据
            var jsonContent = JsonConvert.SerializeObject(testDetails);
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            // 发送请求
            var response = await client.PostAsync($"{GV.ServerAddress}/Data/HistoryDataInsert", content);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            var result = JsonConvert.DeserializeObject<ApiResult>(responseString);

            // 如果同步失败，记录日志
            if (!result.success)
            {
                await LogSyncFailureAsync(
                    JsonConvert.SerializeObject(testDetails),
                    result.message,
                    "Data/DataInsert"
                );
            }

            return result;
        }
        catch (Exception ex)
        {
            // 发生异常时也记录日志
            await LogSyncFailureAsync(
                JsonConvert.SerializeObject(testDetails),
                ex.Message,
                "Data/DataInsert"
            );

            return new ApiResult 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }

    // 添加参数数据模型
    public class ParamData
    {
        public string name { get; set; }
        public int type { get; set; }
        public string des { get; set; }
        public int? channelCount { get; set; }
        public string displayStyle { get; set; }
        public int ver { get; set; }
        public string createdBy { get; set; }
        public string createdTime { get; set; }
        public bool inUse { get; set; }
        public byte[] fileData { get; set; }
    }

    public static async Task<bool> UploadSingleTestConfigToMes(TestConditions testConfig)
    {
        bool actionFlag = true;
        
        int currentType = 0;
        if (GV.InstrumentModel == ViewModels.Entity.GC.InstrumentModelType.TH2837AX48)
        {
            currentType = 108;
        } else
        {
            currentType = 11;
        }
        
        ParamData paramData = new ParamData
        {
            name = testConfig.Name,
            type = currentType,
            des = testConfig.Remarks,
            channelCount = GV.InstrumentModel == IntegratedMeasuring.ViewModels.Entity.GC.InstrumentModelType.TH2837AX48 ? 48 : 20,
            displayStyle = "",
            ver = 0,
            createdBy = "IntegratedMeasuring",
            createdTime = testConfig.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
            inUse = true,
            fileData = testConfig.SourceData,
        };
        ApiResult apiResult = await SyncParamsAsync(new List<ParamData>() { paramData });
        if (apiResult.code != 0)
        {
            actionFlag = false;
        }
        testConfig.IsSynch = true;
        await BaseDataStorage.Instance.UpdateTestConditionsAsync(testConfig);
        return actionFlag;
    }
    
    public static async Task<bool> UploadTestConfigToMes()
    {
        bool actionFlag = true;
        
        int currentType = 0;
        if (GV.InstrumentModel == ViewModels.Entity.GC.InstrumentModelType.TH2837AX48)
        {
            currentType = 108;
        } else
        {
            currentType = 11;
        }
        // 查询本地未同步的机种参数
        var paramList = await BaseDataStorage.Instance.QueryParamAboutNotSynch();
        for (int i = 0; i < paramList.Count; i++)
        {
            var param = paramList[i];
            ParamData paramData = new ParamData
            {
                name = param.Name,
                type = currentType,
                des = param.Remarks,
                channelCount = GV.InstrumentModel == IntegratedMeasuring.ViewModels.Entity.GC.InstrumentModelType.TH2837AX48 ? 48 : 20,
                displayStyle = "",
                ver = 0,
                createdBy = "IntegratedMeasuring",
                createdTime = param.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                inUse = true,
                fileData = param.SourceData,
            };
            ApiResult apiResult = await SyncParamsAsync(new List<ParamData>() { paramData });
            if (apiResult.code != 0)
            {
                actionFlag = false;
                break;
            }
            paramList[i].IsSynch = true;
            await BaseDataStorage.Instance.UpdateTestConditionsAsync(paramList[i]);
        }
        return actionFlag;
    }
    
    // 添加同步参数的方法
    public static async Task<ApiResult> SyncParamsAsync(List<ParamData> paramList)
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) return apiResult;
        try
        {
            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 序列化数据
            var jsonContent = JsonConvert.SerializeObject(paramList);
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");

            // 发送请求
            var response = await client.PostAsync($"{GV.ServerAddress}/Param/BatchInsert", content);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            var result = JsonConvert.DeserializeObject<ApiResult>(responseString);

            // 如果同步失败，记录日志
            if (!result.success)
            {
                await LogSyncFailureAsync(
                    JsonConvert.SerializeObject(paramList),
                    result.message,
                    "Param/BatchInsert"
                );
            }

            return result;
        }
        catch (Exception ex)
        {
            // 发生异常时也记录日志
            await LogSyncFailureAsync(
                JsonConvert.SerializeObject(paramList),
                ex.Message,
                "Param/BatchInsert"
            );

            return new ApiResult 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }

    // 添加查询参数类
    public class ParamQueryParams
    {
        public string name { get; set; }
        public int? type { get; set; }
        public int? inUse { get; set; }
    }

    // 添加参数列表响应类
    public class ParamListResponse : ApiResult
    {
        public new List<ParamData> data { get; set; }
    }
    
    /// <summary>
    /// 将服务器数据与本地数据进行合并去重
    /// </summary>
    /// <returns>合并操作是否成功</returns>
    public static async Task<bool> MergeAndRemoveDuplicatesAsync()
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) return false;
        try
        {
            // 获取当前仪器类型
            int currentType = 0;
            if (GV.InstrumentModel == ViewModels.Entity.GC.InstrumentModelType.TH2837AX48)
            {
                currentType = 108;
            } else
            {
                currentType = 11;
            }
        
            // 从服务器获取参数列表
            var result = await GetParamListByNameAsync(new ParamQueryParams 
            { 
                type = currentType,
                inUse = 1
            });
        
            if (!result.success)
            {
                // GI._logger.Error($"从服务器获取参数列表失败: {result.message}");
                return false;
            }
        
            if (result.data == null || !result.data.Any())
            {
                // GI._logger.Info("服务器没有可用的参数数据");
                return true;
            }
            
            // 去重result.data中name相同的项， 如果存在name和type相同的项，则保留ver最大的项
            result.data = result.data.GroupBy(param => param.name)
                .Select(group => group.OrderByDescending(param => param.ver).First())
                .ToList();
            
            // 去除result.data中fileData 长度不为9600的项
            result.data = result.data.Where(param => param.fileData.Length == ViewModels.Entity.GC.InstrumentModelTypeDict[(int)GV.InstrumentModel].TestFileDataLength).ToList();
        
            // 将符合条件的文件更新本地参数列表
            foreach (var serverParam in result.data)
            {
                TestConditions testConditions = new TestConditions();
                testConditions.Name = serverParam.name;
                testConditions.ApplicableInstrument = currentType;
                testConditions.CreateTime = DateTime.Now;
                testConditions.Remarks = serverParam.des;
                testConditions.SourceData = serverParam.fileData;
                testConditions.IsSynch = true;
                await BaseDataStorage.Instance.SaveTestConditionsAsync(testConditions);
            }
        
            // 本地未同步的参数上传
            UploadTestConfigToMes();
            
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    
    /// <summary>
    /// 根据条件获取参数列表
    /// </summary>
    /// <param name="queryParams">查询参数</param>
    /// <returns>参数列表响应结果</returns>
    public static async Task<ParamListResponse> GetParamListByNameAsync(ParamQueryParams queryParams)
    {
        ApiResult apiResult;
        if (!VerifyAvailable(out apiResult)) 
            return new ParamListResponse 
            { 
                code = apiResult.code,
                success = false,
                message = apiResult.message,
                data = null
            };

        try
        {
            // 构建查询字符串
            var queryString = new List<string>();
            if (!string.IsNullOrEmpty(queryParams.name))
                queryString.Add($"name={Uri.EscapeDataString(queryParams.name)}");
            if (queryParams.type.HasValue)
                queryString.Add($"type={queryParams.type.Value}");
            if (queryParams.inUse.HasValue)
                queryString.Add($"inUse={queryParams.inUse.Value}");

            var url = $"{GV.ServerAddress}/Param/GetParamListByName";
            if (queryString.Any())
                url += "?" + string.Join("&", queryString);

            // 设置请求头
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("secret", GV.Token);

            // 发送请求
            var response = await client.GetAsync(url);
            
            // 读取响应
            var responseString = await response.Content.ReadAsStringAsync();
            
            // 反序列化响应
            var result = JsonConvert.DeserializeObject<ParamListResponse>(responseString);

            // 如果请求失败，记录日志
            if (!result.success)
            {
                await LogSyncFailureAsync(
                    JsonConvert.SerializeObject(queryParams),
                    result.message,
                    "Param/GetParamListByName"
                );
            }

            return result;
        }
        catch (Exception ex)
        {
            // 发生异常时记录日志
            await LogSyncFailureAsync(
                JsonConvert.SerializeObject(queryParams),
                ex.Message,
                "Param/GetParamListByName"
            );

            return new ParamListResponse 
            { 
                code = 1,
                success = false,
                message = ex.Message,
                data = null
            };
        }
    }
}

public class ApiResult
{
    public int code { get; set; }  // 0成功，1失败，2鉴权失败
    public string data { get; set; }
    public string message { get; set; }
    public bool success { get; set; }
}

public class MesOrdersSchema
{
    public string order { get; set; }
    public string param { get; set; }
    public string instrument { get; set; }
    public int orderNum { get; set; }
    public int finishedNum { get; set; }
    public int defects { get; set; }
    public int accepts { get; set; }
    public string createdBy { get; set; }
    public string createdTime { get; set; }
    public string updatedBy { get; set; }
    public string updatedTime { get; set; }
    public bool inUse { get; set; }
    public string lotNum { get; set; }
    public bool isAnc { get; set; } = true;
    public string workStation { get; set; }
}

public class TestDataItem
{
    public int PRI { get; set; }
    public int SEC { get; set; }
    public string Pin { get; set; }
    public string ShortPin { get; set; }
    public string ItemType { get; set; }
    public string Freq { get; set; }
    public string Vol { get; set; }
    public string Val { get; set; }
    public string Nominal { get; set; }
    public string Min { get; set; }
    public string Max { get; set; }
    public bool Result { get; set; }
    public string ResultValue { get; set; }
    public string Test_Time { get; set; }
}

public class TestData
{
    public List<TestDataItem> Datas { get; set; }
    public bool Result { get; set; }
}

public class TestDetailData
{
    public TestData _Data { get; set; }
    public string Barcode { get; set; }
    public string Batch { get; set; }
    public string ChannelCount { get; set; }
    public string DataId { get; set; }
    public string Duration { get; set; }
    public string EndTime { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }
    public string Field3 { get; set; }
    public string Field4 { get; set; }
    public string Field5 { get; set; }
    public string Field6 { get; set; }
    public string Field7 { get; set; }
    public string Field8 { get; set; }
    public string Field9 { get; set; }
    public string FixtureType { get; set; }
    public int Id { get; set; }
    public string Line { get; set; }
    public string Operator { get; set; }
    public string Order { get; set; }
    public string OutputCount { get; set; }
    public string Param { get; set; }
    public int ProductIndex { get; set; }
    public object restResultDto { get; set; }
    public string Result { get; set; }
    public string Sn { get; set; }
    public string StartTime { get; set; }
    public string Station { get; set; }
    public int Ver { get; set; }
    public int OrderNumber { get; set; }
    public int FinishedNum { get; set; }
    public int Defects { get; set; }
    public int Accepts { get; set; }
}
public class SyncLogData
{
    public int id { get; set; }
    public string data { get; set; }
    public string failReason { get; set; }
    public DateTime addTime { get; set; }
    public string syncUrl { get; set; }
}